﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using System.Data.Entity;
using ANGFLib;
using AngfWebPlayer3;
using AngfWebPlayer3.Models;

// dummy
namespace ANGFSessionWrapper
{
    internal class ScenarioThread
    {
        private const bool 既読スキップ = true;
        [Obsolete]
        public static System.Windows.Forms.Form GetMainForm() { return null; }
        private static UIActionSet humanActions = new UIActionSet();
        [Obsolete]
        public static AutoResetEvent scenarioBlockEvent = null; //new AutoResetEvent(false);

        public static void RestoreActionSet()
        {
            UI.Actions = humanActions;
            SystemFile.EndPlayback();
            DateTime endDateTime = DateTime.Now;
            DefaultPersons.システム.Say(ANGFLib.Constants.スキップ例外Prefix + string.Format("{0}", endDateTime - Util.JounaligStartDateTime));
        }
        public static void TellAssertionFailed(string message)
        {
            humanActions.tellAssertionFailed(message);
        }
        public static void ProgressStatus(string message)
        {
            humanActions.progressStatus(message);
        }
        public static void ResetGameStatus()
        {
            humanActions.ResetGameStatus();
        }
        public static AutoResetEvent AskForUserEvent = new AutoResetEvent(false);
        public static AutoResetEvent ContinueEvent = new AutoResetEvent(false);
        public static int SimpleMenuResult { get; set; }
        public static string SimpleStringResult { get; set; }

        /// <summary>
        /// シナリオ実行のためのメインスレッドメソッド
        /// このメソッドは、どこで強制中断されても問題を残さないようになっていなければならない
        /// データのセーブなど、中断されると問題が起きる処理はUIスレッド側でInvokeさせる必要がある
        /// </summary>
        private static void ScenarioThreadProc()
        {
            RenderingQueue.Clear();
            try
            {
                humanActions.ResetGameStatus = () => { };
                humanActions.ResetDisplay = () => { };
                humanActions.messageOutputMethod = (talker, message) =>
                    {
                        RenderingQueue.Add(new QueueMessage(talker, message));
                    };
                humanActions.simpleMenuMethod = (prompt, items, systemMenu) =>
                    {
                        RenderingQueue.Add(new QueueSimpleMenu(prompt, items, systemMenu));
                        AskForUserEvent.Set();
                        ContinueEvent.WaitOne();
                        int resultCode = SimpleMenuResult;
                        if (resultCode == -1 && systemMenu != null && systemMenu.SimpleMenuAction != null) systemMenu.SimpleMenuAction();
                        else if (resultCode != -1 && items[resultCode].SimpleMenuAction != null) items[resultCode].SimpleMenuAction();
                        return resultCode;
                    };
                humanActions.enterPlayerName = delegate(string prompt, string defaultValue)
                {
                    for (; ; )
                    {
                        RenderingQueue.Add(new QueueSimpleInputString(prompt, defaultValue));
                        AskForUserEvent.Set();
                        ContinueEvent.WaitOne();
                        if (!string.IsNullOrWhiteSpace(SimpleStringResult)) return SimpleStringResult;
                        humanActions.messageOutputMethod(DefaultPersons.システム, "何も入力されていません。入力をお願いいたします。");
                    }
                };
                humanActions.saveFileName = (prompt) =>
                    {
                        // TBW render menu
                        // TBW tell main thread to build page and return
                        // TBW recieve result from user and continue
                        return "";  // dummy
                    };
                humanActions.loadFileName = delegate(string prompt)
                    {
                        // TBW render menu
                        // TBW tell main thread to build page and return
                        // TBW recieve result from user and continue
                        return "";  // dummy
                    };
                humanActions.loadFileNameFromAutoSave = delegate(string prompt)
                    {
                        // TBW render menu
                        // TBW tell main thread to build page and return
                        // TBW recieve result from user and continue
                        return "";  // dummy
                    };
                humanActions.consumeItemMenu = delegate()
                {
                    // TBW render menu
                    // TBW tell main thread to build page and return
                    // TBW recieve result from user and continue
                    Item selectedItem = null;   // TBW
                    if (selectedItem.IsConsumeItem)
                    {
                        bool isConsumed = selectedItem.消費();
                        if (isConsumed)
                        {
                            State.SetItemCount(selectedItem, State.GetItemCount(selectedItem) - 1);
                        }
                        return isConsumed;
                    }
                    else
                    {
                        DefaultPersons.システム.Say("{0}を使いました。", selectedItem.HumanReadableName);
                        DefaultPersons.システム.Say("しかし何も起こりませんでした。");
                        return true;
                    }
                };

                humanActions.selectOneItem = delegate()
                {
                    // TBW render menu
                    // TBW tell main thread to build page and return
                    // TBW recieve result from user and continue
                    return null;   // TBW
                };

                humanActions.shopSellMenu = delegate(GetPriceInvoker getPrice)
                {
                    // TBW render menu
                    // TBW tell main thread to build page and return
                    // TBW recieve result from user and continue
                    return true;
                };

                humanActions.shopBuyMenu = delegate(Item[] sellingItems, GetPriceInvoker getPrice)
                {
                    // TBW render menu
                    // TBW tell main thread to build page and return
                    // TBW recieve result from user and continue
                    return true;
                };
                humanActions.equipMenu = delegate()
                {
                    // TBW render menu
                    // TBW tell main thread to build page and return
                    // TBW recieve result from user and continue
                    return true;
                };
                humanActions.sleepFlash = delegate()
                {
                    // TBW render menu
                    // TBW tell main thread to build page and return
                    // TBW recieve result from user and continue
                    return true;
                };
                humanActions.tellAssertionFailed = delegate(string message)
                {
                    // TBW render it
                    // TBW terminate it
                };
                humanActions.progressStatus = delegate(string message)
                {
                    // TBW
                };
                humanActions.砂時計セット実行 = delegate(bool on)
                {
                    // TBW
                };
                humanActions.ExportFileName実行 = (filename, title) =>
                {
                    // TBW
                    return null;    // TBW
                };
                humanActions.ImportFileName実行 = (filename, title) =>
                {
                    // TBW
                    return null;    // TBW
                };
                humanActions.ShowTotalReport = () =>
                {
                    // TBW
                };
                humanActions.InvokeCollectionList = (id, unlocked, okEnable) =>
                {
                    // TBW
                    return null;
                };
                humanActions.ChangeCycle = () =>
                {
                    // TBW
                    return false;   // TBW
                };
                humanActions.CallAnyMethod = (x) =>
                {
                    // TBW
                };
                humanActions.GetMainForm = () => null;
                humanActions.IsSkipping = () =>
                    {
                        // TBW
                        return false;   // TBW
                    };
                humanActions.LoadFile = (Category, Name) =>
                {
                    var context = new MvcBasicContext();
                    var found = context.FileSystems.FirstOrDefault(c => c.Category == Category && c.Name == Name);
                    if (found != null) return found.Body;
                    return new byte[0];
                };
                humanActions.SaveFile = (Category, Name, Body) =>
                {
                    var context = new MvcBasicContext();
                    var found = context.FileSystems.FirstOrDefault(c => c.Category == Category && c.Name == Name);
                    if (found == null)
                    {
                        var entiry = new FileSystem();
                        entiry.Id = Guid.NewGuid().ToString("N");
                        entiry.Category = Category;
                        entiry.Name = Name;
                        entiry.Body =Body;
                        entiry.UserId = State.UserId;
                        context.FileSystems.Add(entiry);
                    }
                    else
                    {
                        found.Category = Category;
                        found.Name = Name;
                        found.Body =Body;
                        context.Entry(found).State = EntityState.Modified;
                    }
                    context.SaveChanges();

                    // TBW
                    return false;   // TBW
                };

                UI.Actions = humanActions;

                // UI.Actionsが有効になって以後にのみ呼び出されるべき
                General.CallAllModuleMethod((m) => { m.OnStart(); });
                Util.MainLoop();

                new AutoResetEvent(false).WaitOne();	// 待っている途中でフォームスレッドからアボートされる
            }
            catch (ThreadAbortException)
            {
                // nop (レポートさせる例外ではない)
            }
#if !DEBUG
            //catch (Exception e)
            //{
            //    if (System.Diagnostics.Debugger.IsAttached) throw;
            //    GetMainForm().Invoke((MethodInvoker)delegate()
            //        {
            //            GetMainForm().ExceptionProxy(e);
            //        });
            //}
#endif
        }

        private static Thread thread;

        public static bool IsActive { get { return thread != null; } }

        public static void RunScenarioMain()
        {
            thread = new Thread(ScenarioThreadProc);
            thread.Start();
        }

        public static void AbortScenarioMain()
        {
            if (thread != null)
            {
                thread.Abort();
                thread.Join();
                thread = null;
            }
        }

        public static List<QueueBase> RenderingQueue = new List<QueueBase>();
        internal static QueueBase[] WaitForReady()
        {
            return RenderingQueue.ToArray();
        }
    }
}
